//===============================================
//  operation for pmic da9030
//  author: zhenguo
//  08-07-05
//===============================================

#include "pmic_da9030.h"
#include "types.h"
#include "t8.h"

#define _TRUE_BATTERY

int I2cReadByte(unsigned char slaveAddr, unsigned char reg, unsigned char * pval);
int I2cWriteByte(unsigned char slaveAddr, unsigned char reg, unsigned char val);
int printk(const char *fmt, ...);

void writeDAregister( char address, char data )    // busy waiting
{
    I2cWriteByte(0x92, address, data);
    return;
}

char readDAregister( char address )    // busy waiting
{
    unsigned char val;
    I2cReadByte(0x92, address, &val);
    return val;
}

void dump_da9030_regs()
{
    printk("General setup:\n");
    printk("\toffset 0x0, PMIC_ID_REG: %x\n", readDAregister(PMIC_ID_REG));
    printk("\toffset 0x1, PMIC_EVENT_A_REG: %x\n", readDAregister(PMIC_EVENT_A_REG));
    printk("\toffset 0x2, PMIC_EVENT_B_REG: %x\n", readDAregister(PMIC_EVENT_B_REG));
    printk("\toffset 0x3, PMIC_EVENT_C_REG: %x\n", readDAregister(PMIC_EVENT_C_REG));
    printk("\toffset 0x4, PMIC_STATUS_REG: %x\n", readDAregister(PMIC_STATUS_REG));
    printk("\toffset 0x5, PMIC_IRQ_MASK_A_REG: %x\n", readDAregister(PMIC_IRQ_MASK_A_REG));
    printk("\toffset 0x6, PMIC_IRQ_MASK_B_REG: %x\n", readDAregister(PMIC_IRQ_MASK_B_REG));
    printk("\toffset 0x7, PMIC_IRQ_MASK_C_REG: %x\n", readDAregister(PMIC_IRQ_MASK_C_REG));
    printk("\toffset 0x8, PMIC_SYS_CTRL_A_REG: %x\n", readDAregister(PMIC_SYS_CTRL_A_REG));
    printk("\toffset 0x9, PMIC_SYS_CTRL_B_REG: %x\n", readDAregister(PMIC_SYS_CTRL_B_REG));
    printk("\toffset 0xA, PMIC_FAULT_LOG_B_REG: %x\n", readDAregister(PMIC_FAULT_LOG_B_REG));

//    printk("System monitoring:\n");
//    printk("\toffset 0x80, PMIC_SYS_CTRL_C_REG: %x\n", readDAregister(PMIC_SYS_CTRL_C_REG));
//    printk("\toffset 0x81, PMIC_FAULT_LOG_C_REG: %x\n", readDAregister(PMIC_FAULT_LOG_C_REG));
//
//    printk("LDO list:\n");
//    printk("\tLDO1,VCC_CAM_DVDD_1P2,       offset 0x90, PMIC_LDO_1_REG: %x\n", readDAregister(PMIC_LDO_1_REG));
//    printk("\tLDO2, VCC_T_FLASH,           offset 0x91, PMIC_LDO_2_3_REG: %x\n", readDAregister(PMIC_LDO_2_3_REG));
//    printk("\tLDO3, VCC_CODEC_DBVDD_2P8,   offset 0x91, PMIC_LDO_2_3_REG: %x\n", readDAregister(PMIC_LDO_2_3_REG));
//    printk("\tLDO4, VCC_CODEC_CORE_1P8,    offset 0x92, PMIC_LDO_4_5_REG: %x\n", readDAregister(PMIC_LDO_4_5_REG));
//    printk("\tLDO5, VCC_CORE_DOC_2P8,      offset 0x92, PMIC_LDO_4_5_REG: %x\n", readDAregister(PMIC_LDO_4_5_REG));
//    printk("\tLDO6, VCC_KEYPAD,            offset 0x93, PMIC_LDO_6_SIMCP_REG: %x\n", readDAregister(PMIC_LDO_6_SIMCP_REG));
//    printk("\tLDO7, VCC_CODEC_AVDD_2P8,    offset 0x94, PMIC_LDO_7_8_REG: %x\n", readDAregister(PMIC_LDO_7_8_REG));
//    printk("\tLDO8, VCC_CAM_AVDD_2P8,      offset 0x94, PMIC_LDO_7_8_REG: %x\n", readDAregister(PMIC_LDO_7_8_REG));
//    printk("\tLDO9, VCC_CAM_IO_2P8,        offset 0x95, PMIC_LDO_9_12_REG: %x\n", readDAregister(PMIC_LDO_9_12_REG));
//    printk("\tLDO10, VCC_WLAN_1P8,         offset 0x10, PMIC_LDO_10_11_REG: %x\n", readDAregister(PMIC_LDO_10_11_REG));
//    printk("\tLDO11, VCC_FM_2P8,           offset 0x10, PMIC_LDO_10_11_REG: %x\n", readDAregister(PMIC_LDO_10_11_REG));
//    printk("\tLDO12, VCC_IRDA_2P8,         offset 0x95, PMIC_LDO_9_12_REG: %x\n", readDAregister(PMIC_LDO_9_12_REG));
//    printk("\tLDO13, NOUSE\n");
//    printk("\tLDO14, VCC_LCD_2P8,          offset 0x12, PMIC_LDO_14_16_REG: %x\n", readDAregister(PMIC_LDO_14_16_REG));
//    printk("\tLDO15, VCC_PLL_1P3,          offset 0x11, PMIC_LDO_15_REG: %x\n", readDAregister(PMIC_LDO_15_REG));
//    printk("\tLDO16, VCC_SRAM_1P1,         offset 0x12, PMIC_LDO_14_16_REG: %x\n", readDAregister(PMIC_LDO_14_16_REG));
//    printk("\tLDO17, NOUSE,                offset 0x14, PMIC_LDO_17_SIMCP0_REG: %x\n", readDAregister(PMIC_LDO_17_SIMCP0_REG));
//    printk("\tLDO18, VCC_IO_2P8,           offset 0x13, PMIC_LDO_18_19_REG: %x\n", readDAregister(PMIC_LDO_18_19_REG));
//    printk("\tLDO19, VCC_BT_2P8,           offset 0x13, PMIC_LDO_18_19_REG: %x\n", readDAregister(PMIC_LDO_18_19_REG));
//
//    printk("\tLDO ENABLE CONTROL,          offset 0x17, PMIC_CTRL1_REG: %x\n", readDAregister(PMIC_CTRL1_REG));
//    printk("\tLDO ENABLE CONTROL,          offset 0x18, PMIC_CTRL2_REG: %x\n", readDAregister(PMIC_CTRL2_REG));
//    printk("\tLDO ENABLE CONTROL,          offset 0x97, PMIC_REG_CTRL1_REG: %x\n", readDAregister(PMIC_REG_CTRL1_REG));
//    printk("\tLDO ENABLE CONTROL,          offset 0x98, PMIC_REG_CTRL2_REG: %x\n", readDAregister(PMIC_REG_CTRL2_REG));
//
//    printk("\tLDO Sleep control1,          offset 0x99, PMIC_REG_SLEEP_CTRL1_REG: %x\n", readDAregister(PMIC_REG_SLEEP_CTRL1_REG));
//    printk("\tLDO Sleep control2,          offset 0x9A, PMIC_REG_SLEEP_CTRL2_REG: %x\n", readDAregister(PMIC_REG_SLEEP_CTRL2_REG));
//    printk("\tLDO Sleep control3,          offset 0x9B, PMIC_REG_SLEEP_CTRL3_REG: %x\n", readDAregister(PMIC_REG_SLEEP_CTRL3_REG));
//
//    printk("LED & Vibrator:\n");
//    printk("\tLed1 control,                offset 0x20, PMIC_LED1_CTRL_REG: %x\n", readDAregister(PMIC_LED1_CTRL_REG));
////    writeDAregister(PMIC_LED1_CTRL_REG, 0xD4);
//    printk("\tLed2 control,                offset 0x21, PMIC_LED2_CTRL_REG: %x\n", readDAregister(PMIC_LED2_CTRL_REG));
////    writeDAregister(PMIC_LED2_CTRL_REG, 0xD4);
//    printk("\tLed3 control,                offset 0x22, PMIC_LED3_CTRL_REG: %x\n", readDAregister(PMIC_LED3_CTRL_REG));
////    writeDAregister(PMIC_LED3_CTRL_REG, 0xD4);
//    printk("\tLed4 control,                offset 0x23, PMIC_LED4_CTRL_REG: %x\n", readDAregister(PMIC_LED4_CTRL_REG));
////    writeDAregister(PMIC_LED4_CTRL_REG, 0xD4);
//    printk("\tLed5 control,                offset 0x24, PMIC_LEDPC_CTRL_REG: %x\n", readDAregister(PMIC_LEDPC_CTRL_REG));
////    writeDAregister(PMIC_LEDPC_CTRL_REG, 0xD4);
//    printk("\tWhite Led control,           offset 0x25, PMIC_WLED_CP_CTRL_REG: %x\n", readDAregister(PMIC_WLED_CP_CTRL_REG));
//    printk("\tVibrator control,            offset 0x26, PMIC_MISC_A_REG: %x\n", readDAregister(PMIC_MISC_A_REG));
//
//    printk("ADC Control:\n");
//    printk("\toffset 0x30, PMIC_ADC_MAN_CTRL_REG: %x\n", readDAregister(PMIC_ADC_MAN_CTRL_REG));
//    printk("\toffset 0x31, PMIC_ADC_AUTO_CTRL1_REG: %x\n", readDAregister(PMIC_ADC_AUTO_CTRL1_REG));
//    printk("\toffset 0x32, PMIC_VBATMON_REG: %x\n", readDAregister(PMIC_VBATMON_REG));
//    printk("\toffset 0x33, PMIC_VBATMON_TXON_REG: %x\n", readDAregister(PMIC_VBATMON_TXON_REG));
//    printk("\toffset 0x34, PMIC_TBAT_HIGHP_REG: %x\n", readDAregister(PMIC_TBAT_HIGHP_REG));
//    printk("\toffset 0x35, PMIC_TBAT_HIGHN_REG: %x\n", readDAregister(PMIC_TBAT_HIGHN_REG));
//    printk("\toffset 0x36, PMIC_TBAT_LOW_REG: %x\n", readDAregister(PMIC_TBAT_LOW_REG));
////    printk("\toffset 0x37, PMIC_ADC_MAN_CTRL_REG: %x\n", readDAregister(PMIC_ADC_MAN_CTRL_REG));
////    printk("\toffset 0x38, PMIC_ADC_MAN_CTRL_REG: %x\n", readDAregister(PMIC_ADC_MAN_CTRL_REG));
////    printk("\toffset 0x39, PMIC_ADC_MAN_CTRL_REG: %x\n", readDAregister(PMIC_ADC_MAN_CTRL_REG));
////    printk("\toffset 0x3A, PMIC_ADC_MAN_CTRL_REG: %x\n", readDAregister(PMIC_ADC_MAN_CTRL_REG));
//    printk("\toffset 0x40, PMIC_MAN_RES_REG: %x\n", readDAregister(PMIC_MAN_RES_REG));
//    printk("\toffset 0x41, PMIC_VBAT_RES_REG: %x\t~~~\n", readDAregister(PMIC_VBAT_RES_REG));
//    printk("\toffset 0x42, PMIC_VBAT_MIN_RES_REG: %x\n", readDAregister(PMIC_VBAT_MIN_RES_REG));
//    printk("\toffset 0x43, PMIC_VBAT_MIN_TXON_REG: %x\t~~~\n", readDAregister(PMIC_VBAT_MIN_TXON_REG));
//    printk("\toffset 0x44, PMIC_ICHMAX_RES_REG: %x\t~~~\n", readDAregister(PMIC_ICHMAX_RES_REG));
//    printk("\toffset 0x45, PMIC_ICHMIN_RES_REG: %x\t~~~\n", readDAregister(PMIC_ICHMIN_RES_REG));
//    printk("\toffset 0x46, PMIC_ICHAVRG_RES_REG: %x\t~~~\n", readDAregister(PMIC_ICHAVRG_RES_REG));
//    printk("\toffset 0x47, PMIC_VCHMAX_RES_REG: %x\n", readDAregister(PMIC_VCHMAX_RES_REG));
//    printk("\toffset 0x48, PMIC_VCHMIN_RES_REG: %x\n", readDAregister(PMIC_VCHMIN_RES_REG));
//    printk("\toffset 0x49, PMIC_TBAT_REG: %x\t~~~\n", readDAregister(PMIC_TBAT_REG));
//    printk("\toffset 0x4A, PMIC_ADC_IN4_RES_REG: %x\n", readDAregister(PMIC_ADC_IN4_RES_REG));
//
//    printk("Battery charger control:\n");
//    printk("\toffset 0x28, PMIC_CHARGER_CTRL_REG: %x\n", readDAregister(PMIC_CHARGER_CTRL_REG));
//    printk("\toffset 0x29, PMIC_CHARGER_CCTR_REG: %x\n", readDAregister(PMIC_CHARGER_CCTR_REG));
//    printk("\toffset 0x2A, PMIC_CHARGER_TCTR_REG: %x\n", readDAregister(PMIC_CHARGER_TCTR_REG));
//    printk("\toffset 0x2B, PMIC_CHARGER_PULSE_REG: %x\n", readDAregister(PMIC_CHARGER_PULSE_REG));
}

int BatCap[12][3] = {
    {4099, 91, 4},//90%
    {4002, 80, 4},//80%
    {3942, 70, 4},//70%
    {3880, 60, 3},//60%
    {3821, 50, 3},//50%
    {3791, 40, 3},//40%
    {3767, 30, 2},//30%
    {3734, 20, 2},//20%
    {3680, 10, 1},//10%
    {3600, 5 , 0},//5%
    {3552, 3 , 0},//3%
    {3495, 2 , 0},//1%
};

int percent(int mv)
{
    int i;
    for(i = 0; i < 11; i++) {
        if (mv > BatCap[i+1][0]) break;
    }
    return (BatCap[i][1] << 16) + BatCap[i][2];
}

/* FUNCTION:Convert the voltage register value to voltage in mv
 *
 */
unsigned int DA9030_RegVal2MV(unsigned int regval)
{
    regval = (regval * 265 / 255 + 265) * 10;

    return regval;
}

/* FUNCTION:Convert the voltage in mv to voltage register value
 *
 */
unsigned int DA9030_MV2RegVal(unsigned int voltage)
{
    voltage = (voltage / 10 - 265) * 255 / 265;

    return voltage;
}

int DetectChargerPresence()
{
    unsigned char status;

    status = readDAregister(PMIC_STATUS_REG);//STATUS
    // Detect the charging state
    if (status & 0x0C) {
        return 1;
    }
    else {
        return 0;
    }
}

void DA9030_Mask_LowBatIrq()
{
    writeDAregister(PMIC_IRQ_MASK_A_REG, readDAregister(PMIC_IRQ_MASK_A_REG) | VBATMON_IRQ);
}

void DA9030_Init_ADC()
{
    writeDAregister(PMIC_ADC_MAN_CTRL_REG, 0xF0); //Enable vcc to ADC
    writeDAregister(PMIC_ADC_AUTO_CTRL1_REG, 0xFF); //Enable auto ADC convert

    writeDAregister(PMIC_VBATMON_REG, 0x48);  //set the low battery voltage ~=3.4v

    //Set TBAT HIGHP
    writeDAregister(PMIC_TBAT_HIGHP_REG, 0x00);
    writeDAregister(PMIC_TBAT_HIGHN_REG, 0xff);
    writeDAregister(PMIC_TBAT_LOW_REG, 0xff);
    writeDAregister(PMIC_CHARGER_PULSE_REG, 0xC7);   // 256 ms
}

unsigned char DA9030_Auto_GetVBAT()
{
    unsigned char vbat_res;

//    StopCharging();
//    Sleep(10);
    vbat_res = readDAregister(PMIC_VBAT_RES_REG);
    printk("PMIC_VBAT_RES_REG = %d\n", vbat_res);

#if 0
    dump_da9030_regs();
    printk("\toffset 0x44, PMIC_ICHMAX_RES_REG: %x\t~~~\n", readDAregister(PMIC_ICHMAX_RES_REG));
    printk("\toffset 0x45, PMIC_ICHMIN_RES_REG: %x\t~~~\n", readDAregister(PMIC_ICHMIN_RES_REG));
    printk("\toffset 0x46, PMIC_ICHAVRG_RES_REG: %x\t~~~\n", readDAregister(PMIC_ICHAVRG_RES_REG));
    printk("\toffset 0x49, PMIC_TBAT_REG: %x\t~~~\n", readDAregister(PMIC_TBAT_REG));
#endif

    return vbat_res;
}

unsigned char DA9030_Auto_GetTBAT()
{
    return readDAregister(PMIC_TBAT_REG);
}

unsigned char DA9030_Auto_GetICHARGE()
{
    return readDAregister(PMIC_ICHAVRG_RES_REG);
}

void  StartCharging(void)
{
    writeDAregister(PMIC_CHARGER_CTRL_REG, CHARGE_1200mA);
}

void  StopCharging(void)
{
    writeDAregister(PMIC_CHARGER_CTRL_REG, 0x00);
}

int IsChargingPresent()
{
    unsigned char status;
    int bCharger_insert;

    status = readDAregister(PMIC_STATUS_REG);//STATUS
    // Detect the charging state
    if (status & 0x0C) {
        bCharger_insert= 1;
    }
    else {
        bCharger_insert= 0;
    }

    return bCharger_insert;
}

int IsACAdapterIn(void)
{
    unsigned char status;
    int  bCharger_instert;

    status = readDAregister(PMIC_STATUS_REG);//STATUS
    if ((status & 0x08) > 0)
        bCharger_instert=1;
    else
        bCharger_instert=0;

    return bCharger_instert;
}

int IsPowerOnOff(void)
{
    unsigned char status;
    int PowerOnOff = 0;

    status = readDAregister(PMIC_STATUS_REG);//STATUS
    if(!(status & (0x1 << 0))) {
        PowerOnOff=1;
    }

   return PowerOnOff;
}

int IsBatteryOK(void)
{
    int rel = 0;
    unsigned short battervul = 0;
    unsigned int VoltageVal = 0;

    battervul = DA9030_Auto_GetVBAT();
    VoltageVal = (battervul * 265 / 255 + 265) * 10;

    if(VoltageVal > 3640) {//old 360
        rel=1;
    }

    return rel;

}

int IsBatteryFull()
{
    unsigned char chgCurrent = readDAregister(PMIC_ICHAVRG_RES_REG);

//    printk("@@In IsBatteryFull, chgCurrent = %x\n", chgCurrent);
    if ((chgCurrent < 0x20) && (chgCurrent > 0)) {
        return 1;
    }
    else
        return 0;
}

/*  Description: Get the current battery voltage. The unit is mV
 *               because kernel can not use float point
 */
unsigned int BatteryGetVoltage()
{
    unsigned int volt = (unsigned int)DA9030_Auto_GetVBAT();

#if  defined(_TRUE_BATTERY)
    volt = (volt * 265 / 255 + 265) * 10;
#else
    volt = 3900;
#endif

    printk("The volt is %d\n", volt);

    return volt;
}

void DA9030_OpenWLed()
{
    char wLedControl = readDAregister(PMIC_WLED_CP_CTRL_REG);
    wLedControl |= (1 << 6);
    writeDAregister(PMIC_WLED_CP_CTRL_REG, wLedControl);
}

void DA9030_CloseWLed()
{
    writeDAregister(PMIC_WLED_CP_CTRL_REG, 0);  //some hardware bug, must set 0.
}

void DA9030_SetWhiteLed(unsigned char blightness)
{
    char wLedControl = readDAregister(PMIC_WLED_CP_CTRL_REG);
//    assert(blightness < 8);
    if (!(blightness < 8)) {
        printk("set error value!\n");
        return;
    }

    wLedControl &= ~0x07;
    wLedControl |= blightness;
    writeDAregister(PMIC_WLED_CP_CTRL_REG, wLedControl);

}

void DA9030_TurnOnVibrate()
{
    char motorControl = readDAregister(PMIC_MISC_A_REG);
    motorControl |= 0x1;
    writeDAregister(PMIC_MISC_A_REG, motorControl);
}

void DA9030_TurnOffVibrate()
{
    char motorControl = readDAregister(PMIC_MISC_A_REG);
    motorControl &= ~0x1;
    writeDAregister(PMIC_MISC_A_REG, motorControl);
}

void DA9030_SetVibrateMode(char mode)
{
    if ((0 == mode) || (1 == mode)) {
        char motorControl = readDAregister(PMIC_MISC_A_REG);
        motorControl &= ~(0x1 << 1);
        motorControl |= (mode << 1);
        writeDAregister(PMIC_MISC_A_REG, motorControl);
    }
    else
        printk("invalid mode for vibrate\n");
}

void DA9030_SetVibrateFeq(unsigned char frequence)
{
//    assert(frequence < 4);
    if (!(frequence < 4)) {
        printk("set error value!\n");
        return;
    }

    char motorControl = readDAregister(PMIC_MISC_A_REG);
    motorControl &= ~(0x3 << 2);
    motorControl |= (frequence << 2);
    writeDAregister(PMIC_MISC_A_REG, motorControl);
}

void DA9030_SetVibrateDuty(unsigned char duty)
{
//    assert(duty < 4);
    if (!(duty < 4)) {
        printk("set error value!\n");
        return;
    }
    char motorControl = readDAregister(PMIC_MISC_A_REG);
    motorControl &= ~(0x3 << 4);
    motorControl |= (duty << 4);
    writeDAregister(PMIC_MISC_A_REG, motorControl);
}



